#!/usr/bin/env python

import os, sys
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
from gtfsrender import CairoRenderer, MercatorProjection, tuples_to_radians
from gtfs.models import *
from django.db.models import Max, Min
import math
from pprint import pprint
import cPickle as pickle
from colourdb import colourdb
from shapereduce import pairwise
import colorsys

route_type_colours = ["red",
                      "green",
                      "blue",
                      "purple",
                      "orange",
                      "gray",
                      "pink",
                      "turqoise"]

def slog(n):
  if n >= 1:
      return math.log(n)
  else:
      return 0

def get_bounds(segments):
    huge_val = 2 << 31
    min_lat, max_lat = huge_val, -huge_val
    min_lon, max_lon = huge_val, -huge_val
    for segment in segments:
      if segment.min_lat < min_lat: min_lat = segment.min_lat
      if segment.max_lat > max_lat: max_lat = segment.max_lat
      if segment.min_lon < min_lon: min_lon = segment.min_lon
      if segment.max_lon > max_lon: max_lon = segment.max_lon
    return {'lat_min' : min_lat,
          'lat_max' : max_lat,
          'lon_min' : min_lon,
          'lon_max' : max_lon }

def render_pts(render, pts, colour, line_width):
  # route = pts[0].shape.trip_set.all()[0].route
  # colour = route_type_colours[route.route_type.id]
  render.line(colour, 
              tuples_to_radians(pt for pt in pts),
              line_width=line_width)

def plot(agency, from_date, to_date, width=1024, padding=2):
    def get_segment_frequencies():
        # for each trip, figure out how often it runs in (from_date, to_date)
        # and count grouping by segment id
        segment_freq = {}
        # optimisation: order by shape id, so we get the segments quicker
        trip_frequencies = {}
        for trip in Trip.objects.filter(route__agency=agency).order_by('shape__id'):
            trip_freq = trip.frequency(from_date, to_date)
            for shapesegment in trip.shape.shapesegments_set.all():
                segment = shapesegment.segment
                if not segment_freq.has_key(segment.id):
                    segment_freq[segment.id] = 0
                segment_freq[segment.id] += trip_freq
            sys.stdout.write('.')
            sys.stdout.flush()
        return segment_freq

    segment_freq_pk = '%s.pk' % agency.name
    try:
        segment_freq = pickle.load(open(segment_freq_pk))
    except IOError, e:
        segment_freq = get_segment_frequencies()
        pickle.dump(segment_freq, open(segment_freq_pk, 'w'), protocol=2)

    min_frequency = min(segment_freq.values())
    max_frequency = max(segment_freq.values())
    minf = slog(min_frequency)
    maxf = slog(max_frequency)
    frange = maxf - minf
    print "min_frequency", min_frequency, "max_frequency", max_frequency, "minf", minf, "maxf", maxf, "frange", frange

    map_range = get_bounds((Segment.objects.get(id=segment_id) for segment_id in segment_freq))
    render = CairoRenderer(int(width),
                           int(padding),
                           (map_range['lat_min'], map_range['lat_max'], 
                            map_range['lon_min'], map_range['lon_max']),
                           MercatorProjection)
    render.bounding_box()

    for idx, segment_id in enumerate(segment_freq):
        segment = Segment.objects.get(id=segment_id)
        freq = segment_freq[segment_id]
        slogper = (slog(freq) - minf) / frange
        line_width = 4 * slogper
        rgb = (slogper, 0., 1. - slogper)
##        print "freq", freq, "slogper", slogper, "line_width", line_width, "hue", h, rgb
        render_pts(render, segment.line_string.array, rgb, line_width)
    render.output("test.png")

def plot_trip(trip_id, width=1024, padding=2):
    trip = Trip.objects.get(id=trip_id)
    shape_segments = trip.shape.shapesegments_set.all().order_by('position')
    segments = [t.segment for t in shape_segments]
    if len(shape_segments) == 0:
        raise Exception("No segments")
    map_range = get_bounds(segments)
    render = CairoRenderer(int(width),
                           int(padding),
                           (map_range['lat_min'], map_range['lat_max'], 
                            map_range['lon_min'], map_range['lon_max']),
                           MercatorProjection)
    render.bounding_box()
    t = 0
    last_pt = None
#    render_pts(render, trip.shape.line_string.array, "blue", 1)
    aa = map(list, trip.shape.line_string)
    bb = []
    for idx, shape_segment in enumerate(shape_segments):
      segment = shape_segment.segment
      bb += map(list, segment.line_string.array)
      print shape_segment.position, len(segment.line_string.array), segment.line_string.array[0], segment.line_string.array[-1], segment.line_string.length
      render_pts(render, segment.line_string.array, ["red", "green", "blue"][idx % 3], 2)
      render.output('trip-%d-%d.png' % (trip_id, idx))

    def write_array(f, a):
        fd = open(f, 'w')
        for i in a:
            fd.write("%s\n" % (repr(i)))
        fd.close()
    write_array('aa.txt', aa)
    write_array('bb.txt', bb)

if __name__ == "__main__":
##    plot_trip(18147)
    dt = datetime.date.today()
    plot(Agency.objects.get(name=sys.argv[1]), dt-datetime.timedelta(days=7), dt, width=int(sys.argv[2]))

